<?php
namespace app\api\logic;

use app\api\cache\Marketing;
use app\api\consDir\ErrorConst;
use app\api\services\ExpressService;
use app\api\services\MemberService;
use app\api\services\PacksService;
use app\api\services\PayService;
use app\api\services\RabbitMqService;
use app\common\libs\Singleton;
use app\common\models\Community\CommunityOrder;
use app\common\models\Packs\PacksOrder;
use app\common\models\Packs\PacksOrderExpress;
use app\common\models\Packs\PacksOrderProducts;
use app\common\utils\CommonUtil;
use app\common\utils\RedLock;
use think\db\exception\DataNotFoundException;
use think\db\exception\DbException;
use think\db\exception\ModelNotFoundException;

class PacksLogic extends BaseLogic
{
    use Singleton;

    /**
     * @throws ModelNotFoundException
     * @throws DataNotFoundException
     * @throws DbException
     */
    public function packsList($name, $page, $pageSize): array
    {
        return PacksService::getInstance()->getPacksList($name, $page, $pageSize);
    }

    /**
     * @throws ModelNotFoundException
     * @throws DataNotFoundException
     * @throws DbException
     */
    public function getPacksInfo($id): array
    {
        return PacksService::getInstance()->getPacksInfo($id);
    }

    /**
     * @throws ModelNotFoundException
     * @throws DataNotFoundException
     * @throws DbException
     */
    public function createPacksOrder($id, $addressId, $packsType, $productsContents)
    {

        if (empty($id) || empty($addressId) || empty($packsType)) {
            CommonUtil::throwException(ErrorConst::PARAM_ERROR, ErrorConst::PARAM_ERROR_MSG);
        }
        $getPacksInfo = PacksService::getInstance()->getPacksInfo($id);
        if (empty($getPacksInfo)) {
            CommonUtil::throwException(ErrorConst::PACKS_NO_EXIST_ERROR, ErrorConst::PACKS_NO_EXIST_ERROR_MSG);
        }
        $addressDetail = MemberService::getInstance()->addressDetail($this->userinfo->id, $addressId);
        if (empty($addressDetail)) {
            CommonUtil::throwException(ErrorConst::PACKS_NO_ADDRESS_ERROR, ErrorConst::PACKS_NO_ADDRESS_ERROR_MSG);
        }
        PacksOrder::getInstance()->startTrans();
        try {
            //生成订单
            $orderData = [
                'member_id'            => $this->userinfo->id,
                'order_no'             => getNo('PA'),
                'packs_id'             => $id,
                'sales_price'          => $getPacksInfo['salesPrice'],
                'real_price'           => $getPacksInfo['salesPrice'],
                'status'               => 0,
                'packs_type'           => $packsType,
                'give_member_level'    => $getPacksInfo['giveMemberLevel'],
                'give_digital_credits' => $getPacksInfo['giveDigitalCredits'],
                'give_digital_assets'  => $getPacksInfo['giveDigitalAssets'],
                'order_at'             => date('Y-m-d H:i:s'),
                'create_at'            => date('Y-m-d H:i:s'),
            ];
            PacksOrder::getInstance()->insertGetId($orderData);
            //判断内容是否为空，为空表示为礼包全部内容
            if (empty($productsContents)) {
                $content = PacksService::getInstance()->getPacksContent($packsType, $getPacksInfo);
                foreach ($content as $v) {
                    //生成订单商品
                    $productsData = [
                        'order_no'   => $orderData['order_no'],
                        'member_id'  => $this->userinfo->id,
                        'packs_type' => $packsType,
                        'title'      => $v['title'],
                        'img'        => $v['img'],
                        'price'      => $v['price'],
                        'number'     => $v['quantity'],
                        'create_at'  => date('Y-m-d H:i:s'),
                    ];
                    PacksOrderProducts::getInstance()->insert($productsData);
                }
            } else {
                foreach ($productsContents as $v) {
                    //生成订单商品
                    $productsData = [
                        'order_no'   => $orderData['order_no'],
                        'member_id'  => $this->userinfo->id,
                        'packs_type' => $packsType,
                        'title'      => $v['title'],
                        'img'        => $v['img'],
                        'price'      => $v['price'],
                        'number'     => $v['quantity'],
                        'create_at'  => date('Y-m-d H:i:s'),
                    ];
                    PacksOrderProducts::getInstance()->insert($productsData);
                }
            }

            //生成快递信息
            unset($addressDetail['id'], $addressDetail['isDefault']);
            $addressDetail['order_no']  = $orderData['order_no'];
            $addressDetail['member_id'] = $orderData['member_id'];
            $addressDetail['create_at'] = date('Y-m-d H:i:s');
            PacksOrderExpress::getInstance()->insert(CommonUtil::camelToUnderLine($addressDetail));
            PacksOrder::getInstance()->commit();
            return $orderData;
        } catch (\Exception $e) {
            PacksOrder::getInstance()->rollback();
            CommonUtil::throwException(ErrorConst::SYSTEM_ERROR, $e->getMessage());
        }
    }

    /**
     * @throws DataNotFoundException
     * @throws ModelNotFoundException
     * @throws DbException
     */
    public function payPacksOrder($orderNo, $payType, $payPassword, $paySubType): array
    {
        if ( ! RedLock::getInstance()->lock('payPaOrder:' . $orderNo, 1)) {
            CommonUtil::throwException(ErrorConst::FREQUENT_ERROR, ErrorConst::FREQUENT_ERROR_MSG);
        }

        //验证支付密码
        if ($payType == 3) {
            $account = MemberService::getInstance()->account($this->userinfo->id);
            if (empty($account)) {
                CommonUtil::throwException(ErrorConst::NO_PAY_PASSWORD_ERROR, ErrorConst::NO_PAY_PASSWORD_ERROR_MSG);
            }
            if ($account['payPwd'] != $payPassword) {
                CommonUtil::throwException(ErrorConst::PAY_PASSWORD_ERROR, ErrorConst::PAY_PASSWORD_ERROR_MSG);
            }
        }
        //获取订单
        $orderInfo = PacksOrder::getInstance()->where('order_no', $orderNo)->find();

        //订单不存在 订单状态错误      订单用户id错误 ，订单时间超时
        if (empty($orderInfo) || $orderInfo['status'] != 0) {
            CommonUtil::throwException(ErrorConst::NO_ORDER_ERROR, ErrorConst::NO_ORDER_ERROR_MSG);
        }

        //余额
        $amountPrice = 0;
        //实付金额
        $payPrice  = $orderInfo['realPrice'];
        $isBalance = 0;
        if ($payType == 3) {
            $userBalance = MemberService::getInstance()->finance($this->userinfo->id);
            if ($payPrice > $userBalance['amount']) {
                CommonUtil::throwException(ErrorConst::NO_PRICE_ERROR, ErrorConst::NO_PRICE_ERROR_MSG);
            }
            $amountPrice = $payPrice;
            $payPrice    = 0;
            $isBalance   = 1;
        }

        $payInfo = packsService::getInstance()->payPacksOrder($orderInfo, $payPrice, $amountPrice, $payType);
        if (empty($payInfo)) {
            CommonUtil::throwException(ErrorConst::SYSTEM_ERROR, ErrorConst::SYSTEM_ERROR_MSG);
        }

        $userInfo = MemberService::getInstance()->getUserInfo($this->userinfo->id);
        if ($isBalance) {
            //余额全付
            $info = [
                'pay_status'   => 3,
                'pay_no'       => $payInfo['pay_no'],
                'money'        => $payInfo['pay_amount'],
                'trade_no'     => '',
                'receipt_data' => '',
            ];
            $event["exchange"] = config('rabbitmq.order_callback_queue');
            RabbitMqService::send($event, $info);
            $pay = [];
        }elseif ($payType == 4) {
            $pay = SandLogic::getInstance()->orderCreate($this->userinfo->id, $payInfo['pay_price'], $payInfo['pay_no']);
        } else {
            $pay = PayService::getInstance()->toPay($payInfo, $userInfo, $payType, $paySubType);
        }

        return ['payInfo' => $pay];
    }

    /**
     * 订单列表
     * @throws ModelNotFoundException
     * @throws DataNotFoundException
     * @throws DbException
     */
    public function getPacksOrderList($status, $page, $pageSize): array
    {
        return PacksService::getInstance()->getPacksOrderList($status, $page, $pageSize, $this->userinfo->id);
    }

    /**
     * 订单详情
     * @throws ModelNotFoundException
     * @throws DataNotFoundException
     * @throws DbException
     */
    public function getPacksOrderDetail($orderId): array
    {
        if (empty($orderId)) {
            CommonUtil::throwException(ErrorConst::PARAM_ERROR, ErrorConst::PARAM_ERROR_MSG);
        }
        $info = PacksService::getInstance()->getPacksOrderInfo($orderId);
        if (empty($info)) {
            CommonUtil::throwException(ErrorConst::PARAM_ERROR, ErrorConst::PARAM_ERROR_MSG);
        }
        return $info;
    }

    /**
     * @throws ModelNotFoundException
     * @throws DataNotFoundException
     * @throws DbException
     */
    public function packsOrderCancel($orderId): bool
    {
        if (empty($orderId)) {
            CommonUtil::throwException(ErrorConst::PARAM_ERROR, ErrorConst::PARAM_ERROR_MSG);
        }
        $info = PacksService::getInstance()->getPacksOrderInfo($orderId);
        if (empty($info)) {
            CommonUtil::throwException(ErrorConst::PARAM_ERROR, ErrorConst::PARAM_ERROR_MSG);
        }
        PacksOrder::getInstance()->where('id', $orderId)->update(['status' => 4]);
        return true;
    }

    /**
     * @throws ModelNotFoundException
     * @throws DataNotFoundException
     * @throws DbException
     */
    public function packsOrderDel($orderId): bool
    {
        if (empty($orderId)) {
            CommonUtil::throwException(ErrorConst::PARAM_ERROR, ErrorConst::PARAM_ERROR_MSG);
        }
        $info = PacksService::getInstance()->getPacksOrderInfo($orderId);
        if (empty($info)) {
            CommonUtil::throwException(ErrorConst::PARAM_ERROR, ErrorConst::PARAM_ERROR_MSG);
        }
        PacksOrder::getInstance()->where('id', $orderId)->update(['deleted' => 1]);
        return true;
    }

    /**
     * @throws ModelNotFoundException
     * @throws DataNotFoundException
     * @throws DbException
     */
    public function packsOrderExpress($orderId): array
    {
        if (empty($orderId)) {
            CommonUtil::throwException(ErrorConst::PARAM_ERROR, ErrorConst::PARAM_ERROR_MSG);
        }
        $info = PacksService::getInstance()->getPacksOrderInfo($orderId);
        if (empty($info)) {
            CommonUtil::throwException(ErrorConst::PARAM_ERROR, ErrorConst::PARAM_ERROR_MSG);
        }
        $express = PacksOrderExpress::getInstance()->where('order_no', $info['orderNo'])->find();
        if (empty($express)) {
            CommonUtil::throwException(ErrorConst::PARAM_ERROR, ErrorConst::PARAM_ERROR_MSG);
        }
        //$data = ExpressService::getInstance()->getExpress($express['expressNo']);
        $data = ExpressService::getInstance()->query([
            'expressNo' => $express['expressNo'],
        ]);
        if (empty($data)) {
            $data['data'] = [];
        }
        return ['expressNo' => $express['expressNo'], 'expressName' => $express['expressName'], 'expressList' => $data['data']];
    }

    /**
     * 确认收货
     * @throws ModelNotFoundException
     * @throws DataNotFoundException
     * @throws DbException
     */
    public function packsOrderConfirm($orderId): bool
    {
        if (empty($orderId)) {
            CommonUtil::throwException(ErrorConst::PARAM_ERROR, ErrorConst::PARAM_ERROR_MSG);
        }
        $info = PacksService::getInstance()->getPacksOrderInfo($orderId);
        if (empty($info)) {
            CommonUtil::throwException(ErrorConst::PARAM_ERROR, ErrorConst::PARAM_ERROR_MSG);
        }
        if ($info['status'] != 2) {
            CommonUtil::throwException(ErrorConst::ORDER_STATUS_ERROR, ErrorConst::ORDER_STATUS_ERROR_MSG);
        }
        $ret = PacksService::getInstance()->confirm($info);
        if ( ! $ret) {
            CommonUtil::throwException(ErrorConst::PACKS_CONFIRM_ERROR, ErrorConst::PACKS_CONFIRM_ERROR_MSG);
        }
        $event["exchange"] = config('rabbitmq.info_queue');
        RabbitMqService::send($event, ['type' => 'member', 'data' => ['id' => $info['memberId']]]);

        // 检查会员等级升级
        try {
            \app\api\services\UserLevelService::getInstance()->checkUpgrade(
                $this->userinfo->id
            );
        } catch (\Exception $e) {
            \think\facade\Log::error($e->getMessage());
        }
        return true;
    }

    /**
     * 确认升级
     * @throws DataNotFoundException
     * @throws ModelNotFoundException
     * @throws DbException
     */
    public function packsUpgrade($orderId): bool
    {
        if (empty($orderId)) {
            CommonUtil::throwException(ErrorConst::PARAM_ERROR, ErrorConst::PARAM_ERROR_MSG);
        }
        $info = PacksService::getInstance()->getPacksOrderInfo($orderId);
        if (empty($info)) {
            CommonUtil::throwException(ErrorConst::PARAM_ERROR, ErrorConst::PARAM_ERROR_MSG);
        }
        if ( ! in_array($info['status'], [1, 2])) {
            CommonUtil::throwException(ErrorConst::ORDER_STATUS_ERROR, ErrorConst::ORDER_STATUS_ERROR_MSG);
        }
        if ($info['isUpgrade'] == 1) {
            CommonUtil::throwException(ErrorConst::ORDER_STATUS_ERROR, ErrorConst::ORDER_STATUS_ERROR_MSG);
        }
        PacksOrder::getInstance()->startTrans();
        try {
            $ret = PacksService::getInstance()->dividend($info['orderNo']);
            if ( ! $ret) {
                PacksOrder::getInstance()->rollback();
                return false;
            }
            $data = [
                'is_upgrade'   => 1,
                'upgrade_time' => date('Y-m-d H:i:s'),
            ];
            $ret = PacksOrder::getInstance()->where('id', $orderId)->update($data);
            if ( ! $ret) {
                PacksOrder::getInstance()->rollback();
                return false;
            }
        } catch (\Exception $e) {
            PacksOrder::getInstance()->rollback();
            CommonUtil::throwException(ErrorConst::PARAM_ERROR, $e->getMessage());
        }
        PacksOrder::getInstance()->commit();
        //同步抢购次数
        $event["exchange"] = config('rabbitmq.info_queue');
        RabbitMqService::send($event, ['type' => 'member', 'data' => ['id' => $this->userinfo->id]]);
        // 检查会员等级升级
        try {
            \app\api\services\UserLevelService::getInstance()->checkUpgrade(
                $this->userinfo->id
            );
        } catch (\Exception $e) {
            \think\facade\Log::error($e->getMessage());
        }
        return true;
    }

    public function packsUpgradeInfo(): array
    {
        $where = [
            ['type','=',3],
            ['status','=',2],
            ['user_id','=',$this->userinfo->id]
        ];
        $lockStatus = CommunityOrder::getInstance()->where($where)->count() > 0 ? 1 : 0;
        $where = [
            ['status','in',[1,2,3]],
            ['member_id','=',$this->userinfo->id]
        ];
        $buyPacksStatus = PacksOrder::getInstance()->where($where)->count() > 0 ? 1 : 0;
        $serviceSet = Marketing::getKeyData('marketing', 'service_set');
        return [
            'buyPacksStatus' => $buyPacksStatus,
            'lockStatus' => $lockStatus,
            'upStatus' => (int)$serviceSet['up_status'] ?? 0
        ];
    }

}
